home *** CD-ROM | disk | FTP | other *** search
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; MODULE: STEPWRAP
- ;;;
- ;;; Purpose: This Module defines all procedures,
- ;;; which are neccessary to wrap an expression
- ;;; that should be single steped.
- ;;;
- ;;; Installation: See "autostep.sc".
- ;;;
- ;;; Notes: All the procedures of this module are bound
- ;;; in one environment called `step-environment'.
- ;;; This makes it easy to remove them with one
- ;;; `unbind' operation.
- ;;; The SCHEME code generated by this module
- ;;; makes calls to some auxilary procedures, which
- ;;; should be bound in the `user-global-environment'.
- ;;; The files "stepaux.sc" and "stepaux.fsl"
- ;;; contain the source code and the compiled
- ;;; code of these procedures.
- ;;;
- ;;; Bugs: 000 Sometimes the procedure `stop-step' is
- ;;; called with the wrong environment.
- ;;; This will show some strange variables,
- ;;; if the `inspector' is called from `stop-step'
- ;;; to inspect the environment. Normally the
- ;;; right environment is among the environment
- ;;; parents of the inspected environment.
- ;;;
- ;;; 001 If bigger procedures are stepped, the resulting
- ;;; contains to many constants, so the compiler
- ;;; tabels may overflow.
- ;;;
- ;;; 002 The expansion of a `step' expression may
- ;;; consumes so much memory, that the system may
- ;;; run out of it.
- ;;;
- ;;; 003 The expansion of a `step' expression
- ;;; lasts to long.
- ;;;
- ;;; 004 Due to the creation of additional environments
- ;;; the form `(eval <expr> <environment>)' can not
- ;;; be stepped. See bug 000.
- ;;;
- ;;; 005 Quasiquotes are treated as a primitve,
- ;;; only their result is shown.
- ;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;;; Define the step environment
- (define
- step-environment
- (make-environment
-
- ;;; Converts symbols to downcase strings to display
- ;;; keyword symbols like `BEGIN' in downcase.
- (define (symbol->downcase-string sym)
- (list->string
- (map char-downcase
- (string->list
- (symbol->string sym)))))
-
- ;;; Recognizes a combination.
- ;;; In SCHEME every proper list is a combination.
- (define (combination? expr)
- (pair? expr))
-
-
- ;;; Recognizes special forms
- (define (special? expr)
- (member
- expr
- '( if
- letrec let let* fluid-let
- lambda named-lambda fluid-lambda
- define set!
- quote quasiquote unquote unquote-splicing
- access fluid
- unbound? fluid-bound?
- delay freeze
- begin begin0
- eval)))
-
-
- ;;; Recognizes macros.
- ;;; This procedure depends on the implemenation details
- ;;; of PCS-SCHEME.
- (define (macro? expr)
- (not
- (null?
- (getprop expr 'pcs*macro))))
-
- ;;; Recognizes a variable.
- ;;; In SCHEME every symbol is a variable,
- ;;; if it is not a keyword for a special form
- ;;; or macro. So it is important to test
- ;;; a symbol first for beeing a keyword,
- ;;; before testing it for a beeing a
- ;;; variable.
- (define (variable? expr)
- (symbol? expr))
-
-
-
- ;;; This procedure produces code to
- ;;; show the values of the parameters of
- ;;; a lambda expression.
- ;;; Special care is taken for optional
- ;;; arguments.
- (define (wrap-procedure-args args)
- (if (null? args)
- '()
- (let loop
- ((arg
- (if (symbol? args)
- args
- (car args)))
- (rest
- (if (symbol? args)
- '()
- (cdr args))))
- `((display " parameter ") (display ',arg) (display " ==> ")
- (pp ,arg)
- (newline)
- ,@(if (null? rest)
- '()
- (loop
- (if (symbol? rest)
- rest
- (car rest))
- (if (symbol? rest)
- '()
- (cdr rest))))))))
-
-
- ;;; This procedure produces code to prepare a
- ;;; `lambda', `named-lambda' or `fluid-lambda'
- ;;; for single steping.
- ;;; For `lambda' and `named-lambda' expressions
- ;;; a call to `wrap-procedure-args' is made to
- ;;; produce code for displaying the parameter
- ;;; values of the procedure to single step.
- ;;; Parameter of `fluid-lambda' expressions
- ;;; are handled directly by this procedure.
- (define (wrap-a-lambda keyword args exprs)
- (define res (gensym))
- `(begin
- (display " ") (display ,(symbol->downcase-string keyword)) (display " ==> ")
- (newline)
- (pp '(,keyword ,args ,@exprs))
- (newline)
- (stop-step (the-environment))
- (,keyword
- ,args
- (if step-leap-mode
- ((lambda ()
- ,@exprs))
- (begin
- ,@(if (or (eq? keyword 'named-lambda)
- (eq? keyword 'define))
- `((display " entry procedure ==> ")
- (display ,(car args))
- (newline))
- '((display " entry procedure")
- (newline)))
- ,@(if (eq? keyword 'fluid-lambda)
- (map (lambda (arg)
- `(begin
- (newline)
- (display ',arg)
- (newline)
- (display " fluid parameter ==> ")
- (pp (fluid ,arg))
- (newline)))
- args)
- (wrap-procedure-args
- (if (or (eq? keyword 'named-lambda)
- (eq? keyword 'define))
- (cdr args)
- args)))
- ; (newline)
- (stop-step (the-environment))
- ((lambda (,res)
- ,@(if (or (eq? keyword 'named-lambda)
- (eq? keyword 'define))
- `((display " exit procedure ==> ")
- (display ,(car args))
- (newline))
- '((display " exit procedure")
- (newline)))
- (display " result ==> ")
- (pp ,res)
- (newline)
- (stop-step (the-environment))
- (set! step-leap-mode #F)
- ,res)
- ((lambda ()
- ,@(wrap-a-list exprs)))))))))
-
-
-
- ;;; This procedure produces the code
- ;;; for stepping a `define' clause.
- ;;; If the `define' clause defines a
- ;;; procedure, the clause is converted
- ;;; to a defintion of simple variable.
- ;;; This conversion is done by a call
- ;;; to `expand-macro', which can be
- ;;; specific to TI-SCHEME.
- (define (wrap-a-define args exprs)
- (let ((expanded-def
- (expand-macro `(define ,args ,@exprs)))
- (value (gensym)))
- (let ((expanded-args (cadr expanded-def))
- (expanded-exprs (cddr expanded-def)))
- `(define ,expanded-args
- ((lambda (,value)
- (display ',expanded-args)
- (newline)
- (display " define ==> ")
- (pp ,value)
- (newline)
- (stop-step (the-environment))
- ,value)
- (begin
- (display " define ==> ")
- (pp '(define ,args ,@exprs))
- (newline)
- (stop-step (the-environment))
- ,@(if (pair? args)
- `((pp '(define ,args ,@exprs))
- (newline)
- (display " procedure define ==> ")
- (pp ',expanded-def)
- (newline)
- (stop-step (the-environment)))
- '())
- ,@(if (null? expanded-exprs)
- `(,((lambda () ; an uninitialized variable is set
- (define dummy) ; to a special implementation dependent
- dummy))) ; value, that is returned by this proc.
- `((step ,@expanded-exprs)))))))))
-
-
-
- ;;; This procedure handels `set!' clauses, including
- ;;; `vector-set!'s and `fluid-set!'s.
- (define (wrap-a-set! arg expr)
- (if (and (pair? arg)
- (eq? (car arg) 'vector-ref))
- `(begin
- (pp '(set! ,arg ,@expr))
- (newline)
- (display " vector-set! ==> ")
- (pp ',(expand-macro `(set! ,arg ,@expr)))
- (newline)
- (stop-step (the-environment))
- (step ,(expand-macro `(set! ,arg ,@expr))))
- (let ((value (gensym)))
- `(set! ,arg
- ((lambda (,value)
- (decrement-call-depth)
- (display ',arg)
- (newline)
- (display " set! ==> ")
- (pp ,value)
- (newline)
- (stop-step (the-environment))
- ,value)
- (begin
- (display " set! ==> ")
- (pp '(set! ,arg ,@expr))
- (newline)
- (stop-step (the-environment))
- (increment-call-depth)
- (step ,@expr)))))))
-
-
-
-
- ;;; This procedure produces code to step thru
- ;;; `let', `letrec' abd `let*' clauses.
- (define (wrap-a-let keyword name var-list exprs)
- `(begin
- (display ,(symbol->downcase-string keyword))
- (display " ==> ")
- (pp '(,keyword ,@name ,var-list ,@exprs))
- (newline)
- (stop-step (the-environment))
- (,keyword
- ,@name
- ,(map
- (lambda (var-binding)
- (let ((value (gensym)))
- `(,(car var-binding)
- ((lambda (,value)
- (display ',(car var-binding))
- (newline)
- (display " bound ==> ")
- (display ,value)
- (newline)
- (stop-step (the-environment))
- ,value)
- (step ,@(cdr var-binding))))))
- var-list)
- ,@(if (null? name)
- `((display " entry block")
- (newline))
- `((display " entry block ==> ")
- (display ',(car name))
- (newline)))
- (stop-step (the-environment))
- ,(let ((value (gensym)))
- `((lambda (,value)
- ,@(if (null? name)
- `((display " exit block")
- (newline)
- (newline))
- `((display " exit block ==> ")
- (display ',(car name))
- (newline)
- (newline)))
- (display " result ==> ")
- (display ,value)
- (newline)
- (stop-step (the-environment))
- ,value)
- ((lambda ()
- ,@(wrap-a-list exprs))))))))
-
-
-
- ;;; This procedure produces code to
- ;;; step through a list of argument
- ;;; expressions.
- (define (wrap-a-list expr-list)
- (map
- (lambda (sub-expr) `(step ,sub-expr))
- expr-list))
-
-
-
- ;;; This procedure produces code to
- ;;; step throug a call to a procedure.
- (define (wrap-a-call expr unwraped-expr)
- (define prc (gensym))
- (define args (gensym))
- (define result (gensym))
- `(begin
- (increment-call-depth)
- ((lambda (,prc . ,args)
- (define ,result)
- (decrement-call-depth)
- (pp ',unwraped-expr)
- (newline)
- (display " evaluation ==> ")
- (newline)
- (pp (cons ,prc ,args))
- (newline)
- (stop-step (the-environment))
- (set! ,result (apply ,prc ,args))
- (pp (cons ,prc ,args))
- (newline)
- (display " application ==> ")
- (pp ,result)
- (newline)
- (stop-step (the-environment))
- ,result)
- ,@expr)))
-
-
- (define (wrap-an-eval keyword unwraped-expr)
- (define expr (gensym))
- (define arg (gensym))
- (define result (gensym))
- (define code (car unwraped-expr))
- (define envs (cdr unwraped-expr))
- (if (null? envs)
- `(begin
- (increment-call-depth)
- ((lambda (,expr)
- (define ,result)
- (decrement-call-depth)
- (pp '(eval ,code))
- (newline)
- (display " evaluation ==> ")
- (newline)
- (pp `(eval ,,expr))
- (newline)
- (stop-step (the-environment))
- (set! ,result (eval `(step ,,expr)))
- (pp `(eval ,,expr))
- (newline)
- (display " application ==> ")
- (pp ,result)
- (newline)
- (stop-step (the-environment))
- ,result)
- (begin
- (newline)
- (display " evaluation ==> ")
- (pp '(eval ,code))
- (newline)
- (stop-step (the-environment))
- (step ,code))))
- (error "can't handle this case")))
-
-
- ;;; This procedure produces code to
- ;;; step all kinds of special forms.
- ;;; Partly this done directly in this
- ;;; procedure, partly by calls to the
- ;;; special purpose procedures listed
- ;;; above.
- (define (wrap-special keyword args)
- (case keyword
- (if
- (let ((value (gensym))
- (pred (gensym))
- (then-part (gensym))
- (else-part (gensym)))
- `(begin
- (display " if ==> ")
- (pp '(if ,@args))
- (newline)
- (stop-step (the-environment))
- (increment-call-depth)
- (let ((,then-part ',(cadr args))
- (,else-part ',(caddr args))
- (,pred (step ,(car args))))
- ((lambda (,value)
- (decrement-call-depth)
- (pp (append
- '(if)
- (list ,pred)
- (list ,then-part)
- (list ,else-part)))
- (newline)
- (display " if ==> ")
- (pp ,value)
- (newline)
- (stop-step (the-environment))
- ,value)
- (if ,pred
- (begin
- (set! ,then-part (step ,(cadr args)))
- ,then-part)
- (begin
- (set! ,else-part (step ,@(cddr args)))
- ,else-part)))))))
- ((quote
- quasiquote unquote unquote-splicing
- access fluid
- delay freeze
- unbound? fluid-bound?)
- `(begin
- (display ,(symbol->downcase-string keyword))
- (display " ==> ")
- (pp '(,keyword ,@args))
- (newline)
- (stop-step (the-environment))
- (,keyword ,@args)))
- ((begin begin0)
- `(begin
- (display ,(symbol->downcase-string keyword))
- (display " ==> ")
- (pp '(,keyword ,@args))
- (newline)
- (stop-step (the-environment))
- (,keyword ,@(wrap-a-list args))))
- ((lambda named-lambda fluid-lambda)
- (wrap-a-lambda keyword (car args) (cdr args)))
- ((letrec let* fluid-let)
- (wrap-a-let keyword '() (car args) (cdr args)))
- (let
- (if (symbol? (car args)) ; is it a named let
- (wrap-a-let
- keyword
- (list (car args)) ; name
- (cadr args) ; var-list
- (cddr args)) ; exprs
- (wrap-a-let keyword '() (car args) (cdr args))))
- (define
- (wrap-a-define (car args) (cdr args)))
- (set!
- (wrap-a-set! (car args) (cdr args)))
- (eval
- (wrap-an-eval keyword args))))
-
-
-
- ;;; This procedure produces code to
- ;;; step a combination, that means a
- ;;; `pair' of expressions.
- (define (wrap-combination expr)
- (cond ((special? (car expr))
- (wrap-special (car expr) (cdr expr)))
- ((macro? (car expr))
- `(begin
- (pp ',expr)
- (newline)
- (display " macro ==> ")
- (pp ',(expand-macro-1 expr))
- (newline)
- (stop-step (the-environment))
- (step ,(expand-macro-1 expr))))
- (else
- `(begin
- (display " call ==> ")
- (pp ',expr)
- (newline)
- (stop-step (the-environment))
- ,(wrap-a-call (wrap-a-list expr) expr)))))
-
-
- ;;; This procedure produces code to
- ;;; to step all kinds of SCHEME expressions
- ;;; which can be steped. The trivial cases
- ;;; like numbers, variables and so on are
- ;;; handled directly by this procedure.
- ;;; Combinations are handled by a call
- ;;; to `wrap-combination'.
- (define (wrap expr)
- (cond ((combination? expr)
- (wrap-combination expr))
- ((number? expr)
- `(begin (display " number ==> ")
- (pp ,expr)
- (newline)
- (stop-step (the-environment))
- ,expr))
- ((null? expr)
- `(begin (display " nil ==> ")
- (pp ,expr)
- (newline)
- (stop-step (the-environment))
- ,expr))
- ((string? expr)
- `(begin (display " string ==> ")
- (pp ,expr)
- (newline)
- (stop-step (the-environment))
- ,expr))
- ((char? expr)
- `(begin (display " character ==> ")
- (pp ,expr)
- (newline)
- (stop-step (the-environment))
- ,expr))
- ((vector? expr)
- `(begin (display " vector ==> ")
- (pp ,expr)
- (newline)
- (stop-step (the-environment))
- ,expr))
- ((variable? expr)
- `(begin (display " variable ") (write ',expr) (display " ==> ")
- (pp ,expr)
- (newline)
- (stop-step (the-environment))
- ; (if (closure? ,expr)
- ; (apply-if (assq 'SOURCE (%reify ,expr 0))
- ; (lambda (source)
- ; (eval ((access wrap step-environment)
- ; (list* 'named-lambda
- ; (cons (cdr (%reify ,expr 0)) (caddr source))
- ; (cdddr source)))))
- ; ,expr)
- ; ,expr) ")"
- ,expr))
-
- (else
- (error "could not single step expression:" expr))))
-
-
- )) ; end of make-environment
-
-
- ;;; This is a simple form of the
- ;;; defintion of the `step' macro
- ;;; which is included here for
- ;;; test purposes.
- ;(macro step
- ; (lambda (expr)
- ; ((access wrap step-environment) (cadr expr))))
-